def versions = ['2.0.1']
def currentVersion = versions[0]

pipeline {
  parameters {
        string(name: 'NAMESPACE', defaultValue: 'fit-heart', description: 'Namespace to deploy to')
        choice(choices: versions, description: 'Select the Version to build and/or deploy', name: 'SERVICE_VERSION')
        booleanParam(name: 'BUILD', defaultValue: true, description: 'Should the project runtime code be built and packaged? This will only be executed for the current SERVICE_VERSION')
        booleanParam(name: 'FORTIFY_SCAN', defaultValue: false, description: 'Should a Fortify scan be executed for the project source code? BUILD must also be selected for this stage to execute and SERVICE_VERSION must be the current version.')
        booleanParam(name: 'BUILD_IMAGE', defaultValue: true, description: 'Should the Docker image be built and pushed to the DTR? BUILD must also be selected for this stage to execute and SERVICE_VERSION must be the current version.')
        booleanParam(name: 'DEPLOY', defaultValue: true, description: 'Should the deployment stage run for the Docker image tagged with the selected SERVICE_VERSION?')
  }
  agent {
    kubernetes {
      label 'kubernetes-deploy'
      defaultContainer 'appbuildtools'
      yaml """
apiVersion: v1
kind: Pod
metadata:
  labels:
    image-build: fit-heart
spec:
  containers:
  - name: appbuildtools
    image: ${env.APPBUILDTOOLS_IMAGE}
    volumeMounts:
    - name: shared-data
      mountPath: /pod-data
    env:
    - name: DOCKER_HOST
      value: tcp://localhost:2375
    command:
    - cat
    tty: true
  - name: docker
    image: docker:18.06
    env:
    - name: DOCKER_HOST
      value: tcp://localhost:2375
    command:
    - cat
    tty: true
  - name: docker-fortify
    image: ${env.FORTIFY_IMAGE}
    volumeMounts:
    - name: shared-data
      mountPath: /pod-data
    securitycontext:
      privileged: true
    command:
    - cat
    tty: true
  - name: k8-deploy
    image: ${env.K8_DEPLOY_IMAGE}
    command:
    - cat
    tty: true
  - name: dind-daemon
    image: ${env.DIND_IMAGE}
    securityContext:
      privileged: true
    args:
    - --storage-driver=overlay2
    ports:
    - containerPort: 2375
    volumeMounts:
    - name: docker-graph-storage
      mountPath: /var/lib/docker
    tty: true
  imagePullSecrets:
  - name: ${env.IMAGE_PULL_SECRET}
  volumes:
  - name: docker-graph-storage
    emptyDir: {}
  - name: shared-data
    emptyDir: {}
"""
    }
  }

  environment {
      // Environment variables set for all projects
      APP_NAME = "fit-heart"
      SERVICE_VERSION = "${params.SERVICE_VERSION}"
      IMAGE = "images/map/${APP_NAME}"
      DTR_URL = "${env.DTR_URL}"
      DTR_ORG = "${env.DTR_ORG}"

      // For backward-compatibility with previous pipeline scripts set these environment variables
      APP_VERSION = "${SERVICE_VERSION}"
      DTR_PREFIX = "${DTR_URL}" + "/"
  }

  stages {

    stage('Log Build Environment') {
        steps {
            script {
                // Print key variables
                println("APP_NAME: ${APP_NAME}")
                println("IMAGE: ${IMAGE}")
                println("DTR_URL: ${DTR_URL}")
                println("DTR_ORG: ${DTR_ORG}")
                println("SERVICE_VERSION: ${SERVICE_VERSION}")
                println("Current Version: ${currentVersion}")

                // Print optional variables
                println("APP_VERSION: ${APP_VERSION}")
                println("DTR_PREFIX: ${DTR_PREFIX}")
                println("GIT_COMMIT: ${GIT_COMMIT}")
            }
        }
    }

    stage('Build') {
        steps {
            script {
                // Only execute the build if requested. This supports production-like environments in which only the deploy from a pre-built image is needed.
                if (params.BUILD == true && params.SERVICE_VERSION == currentVersion) {
                    withCredentials([string(credentialsId: 'VA_NEXUS_PWD', variable: 'VA_NEXUS_PWD'),
                                      string(credentialsId: 'VA_NEXUS_USER', variable: 'VA_NEXUS_USER'),
                                      string(credentialsId: 'MAP_DTR_PWD', variable: 'MAP_DTR_PWD'),
                                      string(credentialsId: 'MAP_DTR_USER', variable: 'MAP_DTR_USER'),
                                      string(credentialsId: 'VA_GL_PWD', variable: 'VA_GL_PWD'),
                                      string(credentialsId: 'VA_GL_USER', variable: 'VA_GL_USER')]) {
                        container('appbuildtools') {
                            sh './nextgen/build.sh'
                        }
                    }
                }
                else {
                  println("Skipping build for this project as the BUILD parameter was not selected or selected SERVICE_VERSION is not the current version.")
                }
            }
        }
    }

    stage('Fortify Scan'){
        steps {
            script {
                // Only execute the Fortify scan if the source code was built and the Fortify scan parameter is set
                // The check for BUILD below is needed as a build is a prerequisite for the Fortify scan
                // The FORTIFY parameter supports cases where we want to skip Fortify even when the project is built
                if (params.BUILD == true && params.FORTIFY_SCAN == true && params.SERVICE_VERSION == currentVersion) {
                    withCredentials([string(credentialsId: 'VA_NEXUS_PWD', variable: 'VA_NEXUS_PWD'), string(credentialsId: 'VA_NEXUS_USER', variable: 'VA_NEXUS_USER'), string(credentialsId: 'MAP_DTR_PWD', variable: 'MAP_DTR_PWD'), string(credentialsId: 'MAP_DTR_USER', variable: 'MAP_DTR_USER'), string(credentialsId: 'VA_GL_PWD', variable: 'VA_GL_PWD'), string(credentialsId: 'VA_GL_USER', variable: 'VA_GL_USER')]) {
                        container('docker-fortify') {
                            sh './nextgen/fortify.sh'
                            archiveArtifacts artifacts: '**/fortify/*', fingerprint: true
                        }
                    }
                }
                else {
                    println("Skipping Fortify scan for this project as the BUILD and FORTIFY_SCAN parameters were not both selected")
                }
            }
        }
    }

    stage('Image Build and Push') {
        steps {
            script {
                // Building the project is a prerequisite for building an image and pushing to the Docker Registry
                if (params.BUILD == true && params.BUILD_IMAGE == true && params.SERVICE_VERSION == currentVersion) {
                    withCredentials([string(credentialsId: 'MAP_DTR_PWD', variable: 'MAP_DTR_PWD'), string(credentialsId: 'MAP_DTR_USER', variable: 'MAP_DTR_USER')]) {
                        container('docker') {
                          sh 'docker login -u $MAP_DTR_USER -p $MAP_DTR_PWD $DTR_URL'
                          sh 'docker build -f ./nextgen/Dockerfile --build-arg DTR_URL=$DTR_URL --build-arg DTR_ORG=$DTR_ORG -t $DTR_URL/$IMAGE:$SERVICE_VERSION .'
                          sh 'docker push $DTR_URL/$IMAGE:$SERVICE_VERSION'
                        }
                    }
                }
                else {
                    println("Skipping image build and push for this project as the BUILD parameter was not selected")
                }
            }
        }
    }

    stage('Deploy') {
        environment {
            /* use double quotes for variable substitution or the env variable will not be evaluated */

            // Standard environment variables for all projects
            K8_CA = "${env.K8_CA}"
            K8_API_ADDR = "${env.K8_API}"
            VAMF_ENVIRONMENT = "${env.MAP_ENVIRONMENT}"
            NAMESPACE = "${params.NAMESPACE}"
            VAULT_ADDR = "${env.VAULT_ADDR}"
            CONSUL_ADDR = "${env.CONSUL_ADDR}"
            SECRET_PATH = "secret/${env.MAP_ENVIRONMENT}/deploy"
            CONSUL_PATH = "appconfig/${env.MAP_ENVIRONMENT}/deploy"
            IMAGE_PULL_SECRET = "${env.IMAGE_PULL_SECRET}"

            // Add environment variables that are specific to this project.
            // Review deployment.yml and service.yml to ensure that all environment variables are present here.
        }

        steps {
            script {
                if (params.DEPLOY == true) {
                    withCredentials([string(credentialsId: 'CONSUL_MASTER_TOKEN', variable: 'CONSUL_TOKEN')]) {
                        container('k8-deploy') {
                            sh 'echo "Deploying $DTR_URL/$IMAGE:$SERVICE_VERSION"'
                            sh '/entrypoint.sh'
                        }
                    }
                }
                else {
                    println("Skipping deployment for this project as DEPLOY was not selected")
                }
            }
        }
    }
  }

  post {
    always {
      cleanWs() /* clean up our workspace */
    }
  }
}
